package com.example.ktdemo.exerciseselection.text;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;

/**
 * FileName: SelectionAnimHotView
 * Author: lzt
 * Date: 2022/10/27 15:35
 * 热度动画控件
 */
public class SelectionAnimHotView extends SelectionAnimHotBaseView {
    //是否绘制中
    private boolean isDrawing = false;
    private boolean isDrawingFirstStep, isDrawingSecondStop, isDrawingThirdStep;
    //绘制的bitmap对象
    private Bitmap mAnimBitmap, mSourceBitmap;
    //传入的对象
    private SelectionAnimHotInfo mSelectionInfo;
    //画笔
    private Paint mPaint;
    //点击的x,y
    private float mTouchX, mTouchY;
    //paint alpha
    private float mPaintAlpha = 255f;
    //位移参数
    private float mMovePosY = 0;
    //动画时长
    private static final long TIMER_DURATION_FIRST = 100;
    private static final long TIMER_DURATION_SECOND = 100;
    private static final long TIMER_DURATION_THIRD = 600;
    //动画标识
    private static final String ANIM_TAG_FIRST = "ANIM_TAG_FIRST";
    private static final String ANIM_TAG_SECOND = "ANIM_TAG_SECOND";
    private static final String ANIM_TAG_THIRD = "ANIM_TAG_THIRD";
    //一阶动画长宽控制
    private static final float ANIM_FIRST_SCALE_START = 0.4f;
    private static final float ANIM_FIRST_SCALE_INTERVAL = 0.6f;
    //三阶动画长宽控制
    private static final float ANIM_THIRD_SCALE_START = 1f;
    private static final float ANIM_THIRD_SCALE_INTERVAL = 0.4f;

    private AnimEventListener mAnimEventListener;

    public SelectionAnimHotView(Context context) {
        super(context);
        init();
    }

    public SelectionAnimHotView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SelectionAnimHotView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    protected int dp2px(int dpValue) {
        return (int) getContext().getResources().getDisplayMetrics().density * dpValue;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!isDrawing) {
                    mTouchX = event.getX();
                    mTouchY = event.getY();
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(1);
        mPaint.setAntiAlias(false);
        mPaint.setDither(false);
    }

    private void releaseParams() {
        isDrawing = false;
        mMovePosY = 0;
        isDrawingFirstStep = false;
        isDrawingSecondStop = false;
        isDrawingThirdStep = false;
        mPaintAlpha = 255;
    }

    /**
     * 1、透明度0%>100%,比例40%>100%。0S到0.1S
     * 2、透明度不变，比例不变0.1>0.2
     * 3、位移20PX，00S>0.2S
     * 4、透明度100%>0%，比例100%>60%，位移100PX，0.2s>0.8S
     * 一阶段动画--0到0.1s
     * 二阶段动画--0.1到0.2s
     * 三阶段动画--0.2到0.8s
     */
    private void drawHotAnim() {
        //生成bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inMutable = true;
        mAnimBitmap = BitmapFactory.decodeResource(getResources(), mSelectionInfo.getTextRes(), options);
        //先按比例缩放
        Matrix matrix = new Matrix();
        int oldWidth = mAnimBitmap.getWidth();
        int oldHeight = mAnimBitmap.getHeight();
        int newWidth = dp2px(mSelectionInfo.getShowWidth());
        float rate = 0;
        if (oldWidth > newWidth) {
            //缩小
            rate = 1 - (((oldWidth - newWidth) * 1.0f) / (oldWidth * 1.0f));
        } else if (oldWidth < newWidth) {
            //放大
            rate = (((newWidth - oldWidth) * 1.0f) / (newWidth * 1.0f)) + 1;
        }
        matrix.postScale(rate, rate);
        mAnimBitmap = Bitmap.createBitmap(mAnimBitmap, 0, 0, oldWidth, oldHeight, matrix, true);
        mSourceBitmap = mAnimBitmap.copy(Bitmap.Config.ARGB_8888, true);
        //先把bitmap缩小到原来的40%
        mAnimBitmap = scaleBitmap(mSourceBitmap, ANIM_FIRST_SCALE_START);
        mPaintAlpha = 255;
        startFirstAnim();
    }

    /**
     * 传入宽高，缩放生成bitmap，按比例
     */
    private Bitmap scaleBitmap(Bitmap srcBitmap, float scale) {
        Matrix matrix = new Matrix();
        int oldWidth = srcBitmap.getWidth();
        int oldHeight = srcBitmap.getHeight();
        matrix.postScale(scale, scale);
        return Bitmap.createBitmap(srcBitmap, 0, 0, oldWidth, oldHeight, matrix, true);
    }

    /**
     * 一阶段动画
     * 以宽高为基准
     */
    private void startFirstAnim() {
        float startRate = 0f;
        float endRate = 100f;
        ValueAnimator valueAnimator = getValueAnimator(ANIM_TAG_FIRST);
        if (valueAnimator != null) {
            valueAnimator.cancel();
        }
        valueAnimator = ValueAnimator.ofFloat(startRate, endRate);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(TIMER_DURATION_FIRST);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cacheValue = (float) animation.getAnimatedValue();
                float percent = (cacheValue / 100f);
                mPaintAlpha = 255 * percent;
                mAnimBitmap = scaleBitmap(mSourceBitmap, (float) (ANIM_FIRST_SCALE_START + (ANIM_FIRST_SCALE_INTERVAL / 100f * cacheValue)));
                mMovePosY = dp2px(5) * percent;
                postInvalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //二阶动画
                if (isDrawing) {
                    startSecondAnim();
                } else {
                    releaseParams();
                }
            }
        });
        mMovePosY = 0;
        isDrawingFirstStep = true;
        isDrawingSecondStop = false;
        isDrawingThirdStep = false;
        valueAnimator.start();
    }

    /**
     * 二阶动画
     */
    private void startSecondAnim() {
        float start = 0f;
        float end = 100f;
        ValueAnimator valueAnimator = getValueAnimator(ANIM_TAG_SECOND);
        if (valueAnimator != null) {
            valueAnimator.cancel();
        }
        valueAnimator = ValueAnimator.ofFloat(start, end);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(TIMER_DURATION_SECOND);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cacheValue = (float) animation.getAnimatedValue();
                float percentValue = (cacheValue / 100f);
                //只有位移
                mMovePosY = dp2px(5) + (dp2px(5) * percentValue);
                postInvalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //三阶动画
                if (isDrawing) {
                    startThirdAnim();
                } else {
                    releaseParams();
                }
            }
        });
        isDrawingFirstStep = false;
        isDrawingSecondStop = true;
        isDrawingThirdStep = false;
        valueAnimator.start();
    }

    /**
     * 三阶动画
     */
    private void startThirdAnim() {
        float start = 0f;
        float end = 100f;
        ValueAnimator valueAnimator = getValueAnimator(ANIM_TAG_THIRD);
        if (valueAnimator != null) {
            valueAnimator.cancel();
        }
        valueAnimator = ValueAnimator.ofFloat(start, end);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(TIMER_DURATION_THIRD);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cacheValue = (float) animation.getAnimatedValue();
                float percentValue = cacheValue / (100.f);
                mPaintAlpha = 255 * (1 - percentValue);
                mMovePosY = dp2px(10) + dp2px(50) * percentValue;
                mAnimBitmap = scaleBitmap(mSourceBitmap, (float) (ANIM_THIRD_SCALE_START - ANIM_THIRD_SCALE_INTERVAL / 100f * cacheValue));
                postInvalidate();
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                releaseParams();
                postInvalidate();
                //完成
                notifyFinishListener();
            }
        });
        isDrawingFirstStep = false;
        isDrawingSecondStop = false;
        isDrawingThirdStep = true;
        valueAnimator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        try {
            if (isDrawing) {
                if (mAnimBitmap == null || mAnimBitmap.isRecycled()) {
                    //bitmap有问题，不再绘制
                    return;
                }
                //真正绘制图片动画
                if (isDrawingFirstStep) {
                    innerOnDrawFirstStep(canvas);
                }
                if (isDrawingSecondStop) {
                    innerOnDrawSecondStep(canvas);
                }
                if (isDrawingThirdStep) {
                    innerOnDrawThirdStep(canvas);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void innerOnDrawFirstStep(Canvas canvas) {
        canvas.save();
        mPaint.setAlpha((int) mPaintAlpha);
        float widthInterval = mAnimBitmap.getWidth() / 2.0f;
        float heightInterval = mAnimBitmap.getHeight() / 2.0f;
        canvas.drawBitmap(mAnimBitmap, mTouchX - widthInterval, mTouchY - mMovePosY - heightInterval, mPaint);
        canvas.restore();
    }


    private void innerOnDrawSecondStep(Canvas canvas) {
        canvas.save();
        float widthInterval = mAnimBitmap.getWidth() / 2.0f;
        float heightInterval = mAnimBitmap.getHeight() / 2.0f;
        canvas.drawBitmap(mAnimBitmap, mTouchX - widthInterval, mTouchY - mMovePosY - heightInterval, mPaint);
        canvas.restore();
    }


    private void innerOnDrawThirdStep(Canvas canvas) {
        canvas.save();
        mPaint.setAlpha((int) mPaintAlpha);
        float widthInterval = mAnimBitmap.getWidth() / 2.0f;
        float heightInterval = mAnimBitmap.getHeight() / 2.0f;
        canvas.drawBitmap(mAnimBitmap, mTouchX - widthInterval, mTouchY - mMovePosY - heightInterval, mPaint);
        canvas.restore();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }

    private void notifyStartListener() {
        if (mAnimEventListener != null) {
            mAnimEventListener.start(mSelectionInfo);
        }
    }

    private void notifyFinishListener() {
        if (mAnimEventListener != null) {
            mAnimEventListener.finish(mSelectionInfo);
        }
    }

    //外部调用---------------------------------------------------------------------------
    public void start(SelectionAnimHotInfo selectionAnimHotInfo) {
        if (selectionAnimHotInfo == null) {
            return;
        }
        if (isDrawing) {
            stop();
            stopAnimAndRemoveCallbacks();
            releaseParams();
            return;
        }
        postDelayed(new Runnable() {
            @Override
            public void run() {
                mSelectionInfo = selectionAnimHotInfo;
                isDrawing = true;
                notifyStartListener();
                drawHotAnim();
            }
        }, 20);
    }

    public void stop() {
        isDrawing = false;
        postInvalidate();
        notifyFinishListener();
    }

    public void reset() {
        stop();
        stopAnimAndRemoveCallbacks();
        releaseParams();
    }

    //监听
    public void setAnimListener(AnimEventListener listener) {
        this.mAnimEventListener = listener;
    }

    public interface AnimEventListener {
        void finish(SelectionAnimHotInfo info);

        void start(SelectionAnimHotInfo info);
    }
}
